#include <stdio.h>
#include <sys/socket.h>
#include <errno.h> // Correct header for perror
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> // Added for close()

#define PORT 8888

int main()
{
    int sock, new_sock;
    struct sockaddr_in my_addr, client_addr;
    socklen_t len; // Correct type for accept's length parameter
    char buf[100];
    char buf2[128];
    int recdata = 0;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket create error!");
        exit(1);
    }

    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(PORT);
    my_addr.sin_addr.s_addr = INADDR_ANY; // Bind to all available interfaces

    if (bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
    {
        perror("bind error!");
        close(sock); // Close socket on error
        exit(1);
    }

    if (listen(sock, 5) < 0)
    {
        perror("listen error!");
        close(sock); // Close socket on error
        exit(1);
    }

    printf("TCP Server listening on port %d...\n", PORT);

    while (1)
    {
        len = sizeof(struct sockaddr_in); // Initialize length before accept
        if ((new_sock = accept(sock, (struct sockaddr *)&client_addr, &len)) < 0)
        {
            // Accept can be interrupted, check errno
            if (errno == EINTR)
            {
                continue; // Retry accept if interrupted by signal
            }
            else
            {
                perror("accept error!");
                // Decide whether to exit or continue listening
                // For simplicity here, we might continue, but real servers need robust handling
                continue; // Continue listening for other connections
                // exit(1); // Original behavior
            }
        }
        else
        {
            printf("server: get connection from %s, port %d socket %d \n",
                   inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), new_sock);

            // Handle communication (this simple server handles one message then closes)
            ssize_t recv_len = recv(new_sock, buf, sizeof(buf) - 1, 0); // Leave space for null terminator

            if (recv_len < 0)
            {
                perror("recv error!");
                // Handle error, maybe close connection
            }
            else if (recv_len == 0)
            {
                printf("the client quit!\n");
                // Client closed connection gracefully
            }
            else
            {
                buf[recv_len] = '\0'; // Null-terminate the received string
                printf("receive message: %s \n", buf);
                recdata = atoi(buf);          // Convert string to integer
                recdata++;                    // Increment
                sprintf(buf2, "%d", recdata); // Convert back to string

                if (send(new_sock, buf2, strlen(buf2), 0) < 0)
                {
                    perror("send data failed\n");
                    // Handle send error
                }
                else
                {
                    printf("Sent response: %s\n", buf2);
                }
            }
            close(new_sock); // Close the client connection socket
            printf("Closed connection from %s, port %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        }
    } // End while(1) - This loop structure suggests handling multiple clients sequentially

    close(sock); // Close the listening socket (though the loop never ends in this code)
    return 0;
}